package cn.ug.pay.service.impl;

import cn.ug.aop.RemoveCache;
import cn.ug.aop.SaveCache;
import cn.ug.bean.base.DataTable;
import cn.ug.bean.status.DeleteStatus;
import cn.ug.core.ensure.Ensure;
import cn.ug.pay.bean.BillGoldBean;
import cn.ug.pay.bean.EverydaySellGoldBean;
import cn.ug.pay.bean.SellGoldRecordBean;
import cn.ug.pay.bean.type.BillGoldTradeType;
import cn.ug.pay.mapper.BillGoldMapper;
import cn.ug.pay.mapper.entity.BillGold;
import cn.ug.pay.service.BillGoldService;
import cn.ug.service.impl.BaseServiceImpl;
import cn.ug.util.BigDecimalUtil;
import cn.ug.util.SerialNumberWorker;
import cn.ug.util.UF;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.dozer.DozerBeanMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

import static cn.ug.config.CacheType.OBJECT;
import static cn.ug.config.CacheType.SEARCH;
import static cn.ug.util.ConstantUtil.NORMAL_DATE_FORMAT;

/**
 * @author kaiwotech
 */
@Service
public class BillGoldServiceImpl extends BaseServiceImpl implements BillGoldService {
	
	@Resource
	private BillGoldMapper billGoldMapper;

	@Resource
	private DozerBeanMapper dozerBeanMapper;

	@Override
	@RemoveCache(cleanSearch = true)
	@Transactional(rollbackFor = Exception.class)
	public int save(BillGoldBean entityBean) {
		// 数据完整性校验
		if(null == entityBean || StringUtils.isBlank(entityBean.getMemberId())) {
			Ensure.that(true).isTrue("00000002");
		}
		BillGold entity = dozerBeanMapper.map(entityBean, BillGold.class);
		if(StringUtils.isBlank(entity.getId())) {
			entity.setId(UF.getRandomUUID());
		}
		if(StringUtils.isBlank(entity.getOrderId())) {
			entity.setOrderId(SerialNumberWorker.getInstance().nextId());
		}
		int rows = billGoldMapper.insert(entity);
		Ensure.that(rows).isLt(1,"00000005");
        return 0;
	}

	@Override
	@RemoveCache(cleanSearch = true, cleanObjectByKeyPosition = 0)
	public int delete(String id) {
		if(StringUtils.isBlank(id)) {
			return 0;
		}

		return billGoldMapper.delete(id);
	}

	@Override
	@RemoveCache(cleanSearch = true, cleanObjectByKeyPosition = 0)
	public int deleteByIds(String[] id){
		if(id == null || id.length<=0){
			return 0;
		}

		return billGoldMapper.deleteByIds(id);
	}

	@Override
	@RemoveCache(cleanSearch = true, cleanObjectByKeyPosition = 0)
	public int removeByIds(String[] id) {
		if(id == null || id.length<=0){
			return 0;
		}

		return billGoldMapper.updateByPrimaryKeySelective(
				getParams()
						.put("id", id)
						.put("deleted", DeleteStatus.YES)
						.toMap()
		);
	}

	@Override
	@SaveCache(cacheType = OBJECT)
	public BillGoldBean findById(String id) {
		if(StringUtils.isBlank(id)) {
			return null;
		}

		BillGold entity = billGoldMapper.findById(id);
		if(null == entity) {
			return null;
		}

		BillGoldBean entityBean = dozerBeanMapper.map(entity, BillGoldBean.class);
		entityBean.setAddTimeString(UF.getFormatDateTime(entity.getAddTime()));
		entityBean.setModifyTimeString(UF.getFormatDateTime(entity.getModifyTime()));
		return entityBean;
	}

	@Override
	@SaveCache(cacheType = SEARCH)
	public DataTable<BillGoldBean> query(String order, String sort, int pageNum, int pageSize, Integer type, Integer tradeType,
									 BigDecimal amountMin, BigDecimal amountMax, LocalDateTime addTimeMin, LocalDateTime addTimeMax,
									 String memberId, String memberName, String memberMobile, String keyword) {
		Page<BillGoldBean> page = PageHelper.startPage(pageNum, pageSize);
		List<BillGoldBean> list = queryDetail(order, sort, null, type, tradeType, amountMin, amountMax, addTimeMin, addTimeMax,
				memberId, memberName, memberMobile, keyword);
		if(list != null && list.size() > 0) {
			for (BillGoldBean bean : list) {
				bean.setRemark(BillGoldTradeType.getRemark(bean.getTradeType()));
			}
		}
		return new DataTable<>(page.getPageNum(), page.getPageSize(), page.getTotal(), list);
	}

	@Override
	public BigDecimal totalAmountByTradeType(String memberId, Integer tradeType, String date) {
		if(StringUtils.isBlank(memberId) || StringUtils.isBlank(date)) {
			return BigDecimal.ZERO;
		}
		LocalDateTime addTimeMin = UF.getDate(date);
		LocalDateTime addTimeMax = addTimeMin.plusDays(1);

		List<BillGoldBean> list = queryDetail(null, null, null, null, tradeType, null, null, addTimeMin, addTimeMax,
				memberId, null, null, null);
		if(null == list || list.isEmpty()) {
			return BigDecimal.ZERO;
		}
		BigDecimal totalAmount = BigDecimal.ZERO;
		for (BillGoldBean o : list) {
			totalAmount = BigDecimalUtil.add(totalAmount, o.getAmount());
		}

		return totalAmount;
	}

    @Override
    public Integer totalNumByTradeTypeTheMonth(String memberId, Integer tradeType) {
        if(StringUtils.isBlank(memberId)) {
            return 0;
        }
        String yearMonth = UF.getFormatDateTime("yyyy-MM-01", UF.getDateTime());

        LocalDateTime addTimeMin = UF.getDate(yearMonth);
        LocalDateTime addTimeMax = addTimeMin.plusMonths(1);

        List<BillGoldBean> list = queryDetail(null, null, null, null, tradeType, null, null, addTimeMin, addTimeMax,
                memberId, null, null, null);
        if(null == list || list.isEmpty()) {
            return 0;
        }

        return list.size();
    }

	@Override
	public List<EverydaySellGoldBean> queryEverydaySellGoldRecords(String payDate) {
		if (StringUtils.isNotBlank(payDate)) {
			int date = Integer.parseInt(StringUtils.replaceAll(payDate, "-", ""));
			SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
			int currentDate = Integer.parseInt(format.format(Calendar.getInstance().getTime()));
			if (date >= currentDate) {
				return null;
			}
			List<EverydaySellGoldBean> result = billGoldMapper.queryEverydaySellGoldRecords(payDate);
			if (result == null || result.size() == 0) {
				EverydaySellGoldBean bean = new EverydaySellGoldBean();
				bean.setPayDate(payDate);
				bean.setPoundage(BigDecimal.ZERO);
				bean.setPayGram(BigDecimal.ZERO);
				bean.setActualAmount(BigDecimal.ZERO);
				result.add(bean);
			}
			return result;
		} else {
			List<EverydaySellGoldBean> result = new ArrayList<EverydaySellGoldBean>();
			SimpleDateFormat dateFormat = new SimpleDateFormat(NORMAL_DATE_FORMAT);
			Calendar calendar = Calendar.getInstance();
			calendar.add(Calendar.DAY_OF_YEAR, -1);
			for (; ; ) {
				EverydaySellGoldBean bean = new EverydaySellGoldBean();
				bean.setPayDate(dateFormat.format(calendar.getTime()));
				result.add(bean);
				if (StringUtils.equals("2018-04-27", dateFormat.format(calendar.getTime()))) {
					break;
				}
				calendar.add(Calendar.DAY_OF_YEAR, -1);
			}
			List<EverydaySellGoldBean> records = billGoldMapper.queryEverydaySellGoldRecords(payDate);
			for (EverydaySellGoldBean bean : result) {
				if (records != null && records.size() > 0) {
					for (EverydaySellGoldBean record : records) {
						if (StringUtils.equals(bean.getPayDate(), record.getPayDate())) {
							bean.setPayGram(record.getPayGram().setScale(5, BigDecimal.ROUND_HALF_UP));
							bean.setPoundage(record.getPoundage().setScale(2, BigDecimal.ROUND_HALF_UP));
							bean.setActualAmount(record.getActualAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
						}
					}
				}
			}
			for (EverydaySellGoldBean bean : result) {
				if (bean.getPayGram() == null) {
					bean.setPayGram(BigDecimal.ZERO);
				}
				if (bean.getActualAmount() == null) {
					bean.setActualAmount(BigDecimal.ZERO);
				}
				if (bean.getPoundage() == null) {
					bean.setPoundage(BigDecimal.ZERO);
				}
			}
			return result;
		}
	}

	@Override
	public List<SellGoldRecordBean> querySellGoldRecord(String payDate, int offset, int size) {
		if (StringUtils.isNotBlank(payDate)) {
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("payDate", payDate);
			params.put("offset", offset);
			params.put("size", size);
			return billGoldMapper.querySellGoldRecord(params);
		}
		return null;
	}

	@Override
	public int countSellGoldRecord(String payDate) {
		if (StringUtils.isNotBlank(payDate)) {
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("payDate", payDate);
			return billGoldMapper.countSellGoldRecord(params);
		}
		return 0;
	}

	/**
	 * 获取数据列表
	 * @param order			排序字段
	 * @param sort			排序方式 desc或asc
	 * @param orderId		订单号
	 * @param type			类型 0:全部 1:转入 2:转出
	 * @param tradeType		交易类型 0:全部 1:投资活期产品  2:定期转活期 3:存金 4:活期转定期 5:提金 6:卖金
	 * @param amountMin		最小资产收支记录金额
	 * @param amountMax		最大资产收支记录金额
	 * @param addTimeMin	最小操作时间
	 * @param addTimeMax	最大操作时间
	 * @param memberId		会员ID
	 * @param memberName	会员名称
	 * @param memberMobile	会员手机
	 * @param keyword		关键字
	 * @return				列表
	 */
	private List<BillGoldBean> queryDetail(String order, String sort, String orderId, Integer type, Integer tradeType,
									   BigDecimal amountMin, BigDecimal amountMax, LocalDateTime addTimeMin, LocalDateTime addTimeMax,
									   String memberId, String memberName, String memberMobile, String keyword){
		if(null != addTimeMax) {
			// 加一天减一秒
			addTimeMax = addTimeMax.plusDays(1).minusSeconds(1);
		}
		List<BillGoldBean> dataList = new ArrayList<>();
		List<BillGold> list = billGoldMapper.query(
				getParams(keyword, order, sort)
						.put("orderId", orderId)
						.put("type", type)
						.put("tradeType", tradeType)
						.put("amountMin", amountMin)
						.put("amountMax", amountMax)
						.put("addTimeMin", addTimeMin)
						.put("addTimeMax", addTimeMax)
						.put("memberId", memberId)
						.put("memberName", UF.escapeSql(memberName))
						.put("memberMobile", UF.escapeSql(memberMobile))
						.toMap());
		for (BillGold o : list) {
			BillGoldBean objBean = dozerBeanMapper.map(o, BillGoldBean.class);
			objBean.setAddTimeString(UF.getFormatDateTime(o.getAddTime()));
			objBean.setModifyTimeString(UF.getFormatDateTime(o.getModifyTime()));
			dataList.add(objBean);
		}
		return dataList;
	}

}

